package com.gph.saviorframework.security.web.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.gph.saviorframework.Constants;
import com.gph.saviorframework.ErrorCode;
import com.gph.saviorframework.SaviorFrameworkException;
import com.gph.saviorframework.common.model.Org;
import com.gph.saviorframework.common.model.Position;
import com.gph.saviorframework.common.model.User;
import com.gph.saviorframework.security.service.OrgService;
import com.gph.saviorframework.security.service.PositionService;
import com.gph.saviorframework.security.service.RoleService;
import com.gph.saviorframework.security.service.UserService;
import com.gph.saviorframework.security.web.editor.OrgEditor;
import com.gph.saviorframework.security.web.editor.PositionEditor;
import com.gph.saviorframework.util.RequestUtil;
import com.gph.saviorframework.util.SecUtils;
import com.gph.saviorframework.util.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by savior on 2016/3/24.
 * 用户控制器
 */
@Controller
@RequestMapping("/" + Constants.FRAMEWORK_REQUEST_PATH + "/user")
public class UserController {
    /** 日志输出 */
    final Logger logger = LoggerFactory.getLogger(UserController.class);

    /** 领域对象名称 */
    private static final String domain = User.class.getSimpleName().toLowerCase();

    /** 视图前缀 */
    private static final String viewPrefix = Constants.FRAMEWORK_REQUEST_PATH + "/" + Constants.MODULE_CATEGORY_SECURITY + "/" + domain + "/"
            + domain + "_";

    /** 用户数据服务 */
    @Autowired
    private UserService userService;

    /** 机构数据服务 */
    @Autowired
    private OrgService orgService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private RoleService roleService;

    /** 国际化资源 */
    @Autowired
    private MessageSourceAccessor messages;

    @Autowired
    private SecurityUtils securityUtils;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
        binder.registerCustomEditor(Org.class, new OrgEditor(orgService));
        binder.registerCustomEditor(Position.class, new PositionEditor(positionService));
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String indexPage() throws SaviorFrameworkException {
        return viewPrefix + "index";
    }

    @RequestMapping(value = "/index", method = RequestMethod.POST)
    @ResponseBody
    public String list(
            @RequestParam(value = Constants.DEFAULT_PAGE_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_PAGE_START) Integer start,
            @RequestParam(value = Constants.DEFAULT_RECORD_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_PAGE_SIZE) Integer limit,
            @RequestParam(value = Constants.DEFAULT_SORT_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_SORT_FIELD) String sort,
            @RequestParam(value = Constants.DEFAULT_DIR_MODEL_KEY, required = false, defaultValue = Constants.DEFAULT_SORT_DIRECTION) String dir,
            @RequestParam(value = "org", required = false, defaultValue = "") String org,
            HttpServletRequest request)
            throws SaviorFrameworkException {
        String json = "";
        Map<String, Object> params = RequestUtil.getQueryMap(request, userService.getFields());
        try {
            json = JSONObject.toJSONString(userService.find(start,limit,sort,dir,params,org));
            logger.info(messages.getMessage("log.info.list", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain)}));
        }
        catch (Exception e) {
            e.printStackTrace();
            logger.error(messages.getMessage("log.error.list", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        return json;
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String createPage() throws SaviorFrameworkException {
        return viewPrefix + "create";
    }

    /**
     * 保存新建数据
     *
     * @param user 数据对象
     * @return
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap create(@ModelAttribute User user) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            securityUtils.setCreateEntity(user);
            user.setPassword(SecUtils.getMD5(Constants.DEFAULT_PASSWORD.getBytes()));
            user.setVersion(Constants.VERSION_INIT_VALUE);
            userService.save(user);

            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            modelMap.addAttribute(Constants.DEFAULT_ID_KEY, user.getUsername());
            logger.info(messages.getMessage("log.info.create", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain), user.getUsername()}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.create", new String[] { securityUtils.getUserFullName(), messages.getMessage(domain) }));
        }
        return modelMap;
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String editPage() throws SaviorFrameworkException {
        return viewPrefix + "edit";
    }

    @RequestMapping(value = "/edit/{username}", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap edit(@PathVariable("username") String username,HttpServletRequest request) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            User user = userService.get(username);
            Position position = user.getPosition();
            Org org = user.getOrg();
            ServletRequestDataBinder binder = new ServletRequestDataBinder(user);
            initBinder(binder);
            binder.bind(request);
            securityUtils.setModifyEntity(user);// 设置修改数据的操作用户及时间信息
            if (!org.getId().equals(user.getOrg().getId())) {
                // 如果机构发生变化,则清除用户岗位和所有角色
                user.setPosition(null);
                userService.clearRole(username);
            }
            else if (!position.getId().equals(user.getPosition().getId())) {
                // 如果岗位发生变化,则清除用户所有角色
                userService.clearRole(username);
            }
            userService.update(user);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.edit", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain), username}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, ErrorCode.UNCAUGHT_EXCEPTION);
            logger.error(messages.getMessage("log.error.edit",
                    new String[] { securityUtils.getUserFullName(), messages.getMessage(domain), username }));
        }
        return modelMap;
    }

    @RequestMapping(value = "/view/{username}", method = RequestMethod.GET)
    public @ResponseBody
    ModelMap get(@PathVariable("username") String username) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            modelMap.addAttribute(Constants.DEFAULT_RECORD_MODEL_KEY, userService.findById(username));
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    @RequestMapping(value = "/position", method = RequestMethod.GET)
    @ResponseBody
    public List<Map<String,Object>> getPosition(@RequestParam(value = "org", required = true) String org) throws SaviorFrameworkException {
        try {
            return positionService.findByOrg(org);
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @RequestMapping(value = "/enable", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap enable(@RequestParam(value = "usernames", required = true) String[] usernames) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Set<User> users = new HashSet<User>();
            User user = null;
            for (String username : usernames) {
                user = userService.get(username);
                if (user != null) {
                    user.setEnabled(true);
                    users.add(user);
                }
            }
            userService.update(users);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    @RequestMapping(value = "/disable", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap disable(@RequestParam(value = "usernames", required = true) String[] usernames) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            Set<User> users = new HashSet<User>();
            User user = null;
            for (String username : usernames) {
                user = userService.get(username);
                if (user != null) {
                    user.setEnabled(false);
                    users.add(user);
                }
            }
            userService.update(users);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    @RequestMapping(value = "/resetpassword", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap resetPassword(@RequestParam(value = "usernames", required = true) String[] usernames) throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            for (String username : usernames) {
                userService.resetPassword(username);
            }
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
    public @ResponseBody
    ModelMap delete(@RequestParam(value = "usernames", required = true) String[] usernames)
            throws SaviorFrameworkException {
        ModelMap modelMap = new ModelMap();
        try {
            userService.deleteByIds(usernames);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
            logger.info(messages.getMessage("log.info.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) usernames, "|")}));
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
            logger.error(messages.getMessage("log.error.delete", new String[]{securityUtils.getUserFullName(), messages.getMessage(domain),
                    StringUtils.arrayToDelimitedString((Object[]) usernames, "|")}));
        }
        return modelMap;
    }

    /**
     * 返回分配角色页面
     *
     * @return 角色授权页面视图名称
     * @throws SaviorFrameworkException
     */
    @RequestMapping(value = "/role", method = RequestMethod.GET)
    public String assignRolePage() throws SaviorFrameworkException {
        return viewPrefix + "role_assign";
    }

    @RequestMapping(value = "/role/{user}", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap assignRole(@PathVariable("user") String user) {
        ModelMap modelMap = new ModelMap();
        try {
            modelMap.addAttribute(Constants.DEFAULT_RECORD_MODEL_KEY, roleService.findByUser(user));
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

    /**
     * 保存用户与角色的关联信息.
     * @param ids 角色id数组
     * @param username 用户名
     * @return
     */
    @RequestMapping(value = "/role", method = RequestMethod.POST)
    @ResponseBody
    public ModelMap saveUserRole(@RequestParam(value = "ids",required = false) String[] ids, @RequestParam("username") String username) {
        ModelMap modelMap = new ModelMap();
        try {
            userService.saveUserRole(ids, username);
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.TRUE);
        }
        catch (Exception e) {
            e.printStackTrace();
            modelMap.addAttribute(Constants.DEFAULT_SUCCESS_KEY, Boolean.FALSE);
            modelMap.addAttribute(Constants.DEFAULT_ERROR_KEY, e.getMessage());
        }
        return modelMap;
    }

}
